// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.moc.service.impl;

import com.liuxinlong.common.*;
import com.liuxinlong.constant.RegionConstants;
import com.liuxinlong.enums.MaterialResumeTypeEnum;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.dao.MaterialDao;
import com.liuxinlong.modules.dao.MaterialResumeDao;
import com.liuxinlong.modules.dao.MocDetailDao;
import com.liuxinlong.modules.dao.MocRecordDao;
import com.liuxinlong.modules.entity.MaterialResume;
import com.liuxinlong.modules.entity.MocDetail;
import com.liuxinlong.modules.entity.MocRecord;
import com.liuxinlong.modules.moc.service.MocDetailService;
import com.liuxinlong.modules.sync.service.SyncService;
import com.liuxinlong.utils.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 变更记录详情服务层实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2022年1月21日
 */
@Service
@Slf4j
public class MocDetailServiceImpl implements MocDetailService {

    @Autowired
    private MocDetailDao mocDetailDao;

    @Autowired
    private ExcelImportService excelImportService;

    @Autowired
    private MaterialResumeDao materialResumeDao;

    @Autowired
    private MocRecordDao mocRecordDao;

    @Autowired
    private MaterialDao materialDao;

    @Autowired
    private SyncService syncService;

    @Override
    public List<Map<String, Object>> pageDetailInfo(Map<String, Object> queryParam) {
        List<MocDetail> originList = mocDetailDao.pageDetailList(queryParam);
        List<Map<String, Object>> resultList = completeResult(originList, (int) queryParam.get("startNum"));
        return resultList;
    }

    @Override
    public int getDetailCount(Map<String, Object> queryParam) {

        return mocDetailDao.getDetailCount(queryParam);
    }

    @Override
    @Transactional
    public void addDetailInfo(MocDetail mocDetail) {
        MocRecord mr = mocRecordDao.selectById(mocDetail.getRecordId());
        String[] regionList = mocDetail.getRegion().split(",");
        for (String region : regionList) {
            MocDetail md = new MocDetail();
            String id = SnowFlake.nextIdStr();
            md.setId(id);
            md.setMaterial(mocDetail.getMaterial());
            md.setRegion(region);
            md.setRecordId(mocDetail.getRecordId());
            md.setDescription(mocDetail.getDescription());
            md.setRemark(mocDetail.getRemark());
            md.setParam(mocDetail.getParam());
            md.setNewValue(mocDetail.getNewValue());
            md.setOldValue(mocDetail.getOldValue());
            mocDetailDao.insert(md);

            MaterialResume materialResume = new MaterialResume();
            materialResume.setId(SnowFlake.nextIdStr());
            materialResume.setSourceId(id);
            materialResume.setMaterialNo(mocDetail.getMaterial());
            materialResume.setOperateTime(mr.getChangeTime());
            materialResume.setContent("参数变更");
            materialResume.setOperateType(MaterialResumeTypeEnum.PARAM_CHANGE.getValue());
            materialResume.setOperateUser(mr.getEnterUser());
            materialResume.setRegion(region);
            materialResumeDao.addResume(materialResume);
        }

    }

    @Override
    @Transactional
    public void updateDetailInfo(MocDetail mocDetail) {
        mocDetailDao.updateById(mocDetail);
        // todo 修改需不需要记录resume
    }

    @Override
    public void deleteDetailInfo(String id) {
        mocDetailDao.deleteById(id);
    }

    private List<Map<String, Object>> completeResult(List<MocDetail> originList, int startNum) {
        if (ObjectUtils.isEmpty(originList)) {
            return new ArrayList<>();
        }
        List<Map<String, Object>> resultList = new ArrayList<>(originList.size());
        // todo 后期替换为本地存储物料信息
//        materialDao.selectBatchIds(originList.stream().map(MocDetail::getMaterial).collect(Collectors.toList()));
        List<String> wpcMaterialList = originList.stream().filter(mocDetail -> StringUtils.equals(mocDetail.getRegion(), RegionConstants.WPCNJ)).map(MocDetail::getMaterial).collect(Collectors.toList());
        List<String> wscMaterialList = originList.stream().filter(mocDetail -> StringUtils.equals(mocDetail.getRegion(), RegionConstants.WSCNJ)).map(MocDetail::getMaterial).collect(Collectors.toList());
        List<String> swtMaterialList = originList.stream().filter(mocDetail -> StringUtils.equals(mocDetail.getRegion(), RegionConstants.SWTNJ)).map(MocDetail::getMaterial).collect(Collectors.toList());
        Map<String, Map<String, Object>> wpcMaterialMap = new HashMap<>();
        Map<String, Map<String, Object>> wscMaterialMap = new HashMap<>();
        Map<String, Map<String, Object>> swtMaterialMap = new HashMap<>();
        if (!ObjectUtils.isEmpty(wpcMaterialList)) {
            wpcMaterialMap = syncService.getMaterials(wpcMaterialList, RegionConstants.WPCNJ);
        }
        if (!ObjectUtils.isEmpty(wscMaterialList)) {
            wscMaterialMap = syncService.getMaterials(wscMaterialList, RegionConstants.WSCNJ);
        }
        if (!ObjectUtils.isEmpty(swtMaterialList)) {
            swtMaterialMap = syncService.getMaterials(swtMaterialList, RegionConstants.SWTNJ);
        }

        int sort = startNum + 1;
        for (MocDetail record : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(record);
            map.put("sort", sort);
            String materialId = record.getMaterial();
            if (StringUtils.equals(record.getRegion(), RegionConstants.WPCNJ)) {
                map.put("name", wpcMaterialMap.containsKey(materialId) ? wpcMaterialMap.get(materialId).get("pt_desc1") : "");
            } else if (StringUtils.equals(record.getRegion(), RegionConstants.WSCNJ)) {
                map.put("name", wscMaterialMap.containsKey(materialId) ? wscMaterialMap.get(materialId).get("pt_desc1") : "");
            } else if (StringUtils.equals(record.getRegion(), RegionConstants.SWTNJ)) {
                map.put("name", swtMaterialMap.containsKey(materialId) ? swtMaterialMap.get(materialId).get("pt_desc1") : "");
            }
            resultList.add(map);
            sort++;
        }
        return resultList;
    }

    @Override
    public ImportResp batchAddDetail(List<MocDetail> dataList, String recordId) {
        MocRecord mr = mocRecordDao.selectById(recordId);
        List<MocDetail> newDataList = new ArrayList<>(dataList.size());
        List<MaterialResume> materialResumeList = new ArrayList<>(dataList.size());
        for (MocDetail mocDetail : dataList) {
            String id = SnowFlake.nextIdStr();
            mocDetail.setId(id);
            mocDetail.setRecordId(recordId);
            newDataList.add(mocDetail);

            MaterialResume materialResume = new MaterialResume();
            materialResume.setId(SnowFlake.nextIdStr());
            materialResume.setSourceId(id);
            materialResume.setMaterialNo(mocDetail.getMaterial());
            materialResume.setOperateTime(mr.getChangeTime());
            materialResume.setContent("参数变更");
            materialResume.setOperateType(MaterialResumeTypeEnum.PARAM_CHANGE.getValue());
            materialResume.setOperateUser(mr.getEnterUser());
            materialResume.setRegion(mocDetail.getRegion());
            materialResumeList.add(materialResume);
        }
        mocDetailDao.insertBatch(newDataList);
        materialResumeDao.insertBatch(materialResumeList);
        ImportResp resp = new ImportResp();
        resp.setRetCode(ReturnCodes.HTTP_SUCCESS.getRetCode());
        resp.setRetMessage("导入变更记录详情信息成功");
        return resp;
    }

    @Override
    public ImportResp importDetails(String fileName) {
        String filePath = fileName;
        return excelImportService.excelFile(filePath, 5, new ExcelImportCallBack() {
            @Override
            public Collection<RowError> checkRow(String[] record) {
                return checkRecordValid(record);
            }

            @Override
            public boolean persistRowToDb(String[] record) {
                MocDetail mocDetail = covertToBean(record);
                return false;
//				try {
//					mocDetailDao.addDetail(mocDetail);
//					return true;
//				} catch (Exception e) {
//					return false;
//				}
            }

            @Override
            public ImportResp partFailure(ImportResp resp) {
                resp.setRetMessage("导入变更记录详情数据部分失败，总数=" + resp.getTotal() + ",失败总数=" + resp.getFailedTotal());
                return resp;
            }

            @Override
            public ImportResp allSuccess(ImportResp resp) {
                resp.setRetMessage("导入变更记录详情数据全部成功，总数=" + resp.getTotal());
                return resp;
            }

            @Override
            public List<Map> convertFailList(List<String[]> failRecords) {
                List<Map> list = new ArrayList<>();
                int sort = 1;
                for (String[] failRecord : failRecords) {
                    Map item = new HashMap();
                    item.put("sort", sort);
                    item.put("material", failRecord[0]);
                    item.put("region", failRecord[1]);
                    item.put("description", failRecord[2]);
                    item.put("param", failRecord[3]);
                    item.put("oldValue", failRecord[4]);
                    item.put("newValue", failRecord[5]);
                    item.put("remark", failRecord[6]);
                    list.add(item);
                    sort++;
                }
                return list;
            }

        });
    }

    /**
     * 转换数据为入库数据
     *
     * @param record 数据记录
     * @return 入库数据
     */
    private MocDetail covertToBean(String[] record) {
        MocDetail mocDetail = new MocDetail();
        mocDetail.setMaterial(record[0].trim());
        mocDetail.setRegion(record[1].trim());
        mocDetail.setDescription(record[2].trim());
        mocDetail.setParam(record[3].trim());
        mocDetail.setOldValue(record[4].trim());
        mocDetail.setNewValue(record[5].trim());
        mocDetail.setRemark(record[6].trim());
        return mocDetail;

    }

    /**
     * 校验参数合法性
     *
     * @param record 导入数据
     * @return 参数合法性
     */
    private Collection<RowError> checkRecordValid(String[] record) {
        List<RowError> rowErrors = new ArrayList<>();
        if (StringUtils.isEmpty(record[0].trim())) {
            addRowError("物料号不能为空", rowErrors);
        } else {
            if (record[0].trim().length() > 20) {
                addRowError("物料号长度不能超过20", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[1].trim())) {
            addRowError("域不能为空", rowErrors);
        } else {
            if (record[1].trim().length() > 20) {
                addRowError("域长度不能超过20", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[2].trim())) {
            addRowError("描述不能为空", rowErrors);
        } else {
            if (record[2].trim().length() > 100) {
                addRowError("描述长度不能超过100", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[3].trim())) {
            addRowError("参数类型不能为空", rowErrors);
        } else {
            if (record[3].trim().length() > 100) {
                addRowError("参数类型长度不能超过100", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[4].trim())) {
            addRowError("原参数不能为空", rowErrors);
        } else {
            if (record[4].trim().length() > 100) {
                addRowError("原参数长度不能超过100", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[5].trim())) {
            addRowError("新参数不能为空", rowErrors);
        } else {
//			String compatibility = record[4].trim();
//			if (!StringUtils.equals(compatibility, "兼容") && !StringUtils.equals(compatibility, "不兼容")) {
//				addRowError("兼容性字段不合法", rowErrors);
//			}
            if (record[5].trim().length() > 100) {
                addRowError("新参数长度不能超过100", rowErrors);
            }
        }
        if (record[6].trim().length() > 200) {
            addRowError("修改说明长度不能超过100", rowErrors);
        }

        return rowErrors;
    }

    /**
     * 添加错误行数据
     *
     * @param errorMessage 错误信息
     * @param rowErrors    错误行数据
     */
    private void addRowError(String errorMessage, List<RowError> rowErrors) {
        RowError rowError = new RowError(errorMessage);
        rowErrors.add(rowError);
    }
}
